home *** CD-ROM | disk | FTP | other *** search
- #define __DebugVersion 1
- /*
- ** Apple Macintosh Developer Technical Support
- **
- ** RamDRVR.c: Driver for RamDisk Sample
- **
- ** by Gordon Sheridan and Jim Luther
- ** modified by Brian Bechtel
- **
- ** File: RamDRVR.c
- **
- ** Copyright © 1992-1994 Apple Computer, Inc.
- ** All rights reserved.
- **
- ** You may incorporate this sample code into your applications without
- ** restriction, though the sample code has been provided "AS IS" and the
- ** responsibility for its operation is 100% yours. However, what you are
- ** not permitted to do is to redistribute the source as "DTS Sample Code"
- ** after having made changes. If you're going to re-distribute the source,
- ** we require that you make it clear in the source that the code was
- ** descended from Apple Sample Code, but that you've made changes.
- **
- ** Change History (most recent first):
- **
- ** Change History (most recent first):
- **
- ** <6> 06/10/94 BL°B Converted to work with Symantec as well.
- ** <5> 05/19/94 BL°B Converted to work with Metrowerks. Added
- ** conditionally compiled main routine for Metrowerks.
- ** <4> 10/23/93 JML Added check for valid globals before accepting
- ** Prime, Control, or Status calls (except the control
- ** and status routines that get and set the globals).
- ** <3> 10/14/93 JML Added support for the following Control and Status
- ** calls: physicalIconCC, mediaIconCC, driveInfoCC,
- ** formatListSC. driveStatusSC now returns a copy
- ** of our DrvQEl. Prime, Control and Status now checks
- ** that ioVRefNum = our drive number. Prime now updates
- ** dCtlPosition so I/O using fsFromMark will work. All
- ** debugging code now hidden with "Panic" macros. Prime
- ** now checks for block aligned I/O (since this is a
- ** block device). All calls now return appropriate error
- ** results.
- ** <2+> 7/26/93 gs Set result = noErr for Status csCode = 8.
- ** <2> 6/29/93 gs Return Drive Stats, miscellaneous clean up.
- ** <1> 6/13/93 gs Allocate space for disk from driver. Clean up comments.
- ** <0> 1/17/90 gs 11:58 PM, first version.
- **/
-
-
- #include "RamDisk.h"
-
- /*****************************************************************************/
- /*
- ** Prototypes
- */
-
- pascal OSErr DRVROpen (ParmBlkPtr pb, DCtlPtr dce);
- pascal OSErr DRVRPrime (ParmBlkPtr pb, DCtlPtr dce);
- pascal OSErr DRVRControl (ParmBlkPtr pb, DCtlPtr dce);
- pascal OSErr DRVRStatus (ParmBlkPtr pb, DCtlPtr dce);
- pascal OSErr DRVRClose (ParmBlkPtr pb, DCtlPtr dce);
-
- /*****************************************************************************/
-
- pascal OSErr DRVROpen (ParmBlkPtr pb, DCtlPtr dce)
- {
- DrvrGlobals *globe;
- OSErr result = noErr;
-
- #pragma unused (pb)
-
- /* set device flags because Device Mgr copied header */
- dce->dCtlFlags |= dCtlEnable | dStatEnable | dWritEnable | dReadEnable | dNeedLock;
- dce->dCtlDelay = 0;
-
-
- if (!dce->dCtlStorage) /* is driver already open ? */
- {
- dce->dCtlStorage = (Handle)NewPtrSysClear(sizeof(DrvrGlobals));
- if (!(Ptr)dce->dCtlStorage)
- {
- result = MemError();
- Panic("\pDRVROpen:NewPtr returned nil");
- }
-
- globe = (DrvrGlobals *)dce->dCtlStorage;
- }
- else
- Panic("\pDRVROpen:2nd open attempt");
-
- return (result);
- }
-
- /*****************************************************************************/
-
- pascal OSErr DRVRPrime (ParmBlkPtr pb, DCtlPtr dce)
- {
- DrvrGlobals *globe;
- unsigned long position;
- unsigned long count;
- short calltype;
- OSErr result;
-
- if (dce->dCtlStorage)
- {
- globe = (DrvrGlobals *)dce->dCtlStorage;
-
- if (globe->driveNumber != 0) /* accept no calls, before the globals are initialized */
- {
- position = dce->dCtlPosition;
- count = pb->ioParam.ioReqCount;
-
- /* Preflight the request for block alignment, size, and range */
- if (((position % 512) == 0) &&
- ((count % 512) == 0) &&
- ((count + position) <= globe->ramSize))
- {
- calltype = 0x00FF & pb->ioParam.ioTrap;
- switch(calltype)
- {
- case aRdCmd:
- /* Read the data */
- BlockMove(&globe->ramDisk[position], pb->ioParam.ioBuffer, count);
- break;
- case aWrCmd:
- /* Write the data */
- BlockMove(pb->ioParam.ioBuffer, &globe->ramDisk[position], count);
- break;
- default:
- Panic("\pDRVRPrime: Call wasn't _Read or _Write");
- break;
- }
-
- dce->dCtlPosition += count; /* Update the position */
- pb->ioParam.ioActCount = count; /* Return the actual count */
-
- result = noErr;
- }
- else
- {
- Panic("\pDRVRPrime: Invalid block request");
- result = paramErr;
- }
- }
- else
- {
- Panic("\pDRVRPrime: Globals aren't initialized");
- result = nsDrvErr;
- }
- }
- else
- {
- Panic("\pDRVRPrime: No dCtlStorage");
- result = notOpenErr;
- }
-
- return (result);
- }
-
- /*****************************************************************************/
-
- pascal OSErr DRVRControl (ParmBlkPtr pb, DCtlPtr dce)
- {
- DrvrGlobals *globe;
- OSErr result = controlErr;
- long size;
- long i;
-
- if (dce->dCtlStorage)
- {
- globe = (DrvrGlobals *)dce->dCtlStorage;
-
- /* Accept only setGlobalsCC call, before the globals are initialized */
- if (pb->cntrlParam.csCode == setGlobalsCC)
- {
- /* Initialize DrvrGlobals */
- BlockMove( *(Ptr *)pb->cntrlParam.csParam,(Ptr)globe, sizeof(DrvrGlobals));
- result = noErr;
- }
- else if (globe->driveNumber != 0)
- {
- switch(pb->cntrlParam.csCode)
- {
- case killIOCC:
- /* What's there to kill? A BlockMove? sure... */
- Panic("\pDRVRControl: KillIO on Ram Disk?");
- break;
-
- case verifyDiskCC:
- result = noErr;
- break;
-
- case formatDiskCC:
- /* zero out ram disk memory */
- size = globe->ramSize / 4;
- for (i = 0 ; i < size; i++)
- ((long *)globe->ramDisk)[i] = 0;
- result = noErr;
- break;
-
- case ejectDiskCC:
- break;
-
- case physicalIconCC:
- /* return pointer to icon and where string */
- *(Ptr *)pb->cntrlParam.csParam = (Ptr)globe->physicalIcon;
- result = noErr;
- break;
-
- case mediaIconCC:
- /* return pointer to icon and where string */
- *(Ptr *)pb->cntrlParam.csParam = (Ptr)globe->mediaIcon;
- result = noErr;
- break;
-
- case driveInfoCC:
- /* high word (bytes 2 & 3) clear */
- /* byte 1 = primary + fixed media + internal */
- /* byte 0 = drive type (0x10 = RAM disk) */
- *(unsigned long *)pb->cntrlParam.csParam = 0x00000410;
- result = noErr;
- break;
-
- case 24: /* ••• Return SCSI csCode Partition Size */
- *(unsigned long *)pb->cntrlParam.csParam = globe->ramSize >> 9;
- result = noErr;
- break;
-
- case accRun:
- result = noErr;
- break;
-
- default:
- Panic("\pUnrecognized control call");
- break;
- }
- }
- else
- {
- Panic("\pDRVRControl: Globals not initialized");
- }
- }
- else
- {
- Panic("\pDRVRControl: No dCtlStorage");
- result = notOpenErr;
- }
-
- return (result);
- }
-
- /*****************************************************************************/
-
- pascal OSErr DRVRStatus (ParmBlkPtr pb, DCtlPtr dce)
- {
- DrvrGlobals *globe;
- OSErr result = statusErr;
- DrvSts *driveStats;
- DrvQElPtr driveQEl;
-
- if (dce->dCtlStorage)
- {
- globe = (DrvrGlobals *)dce->dCtlStorage;
-
- /* Accept only getGlobalsSC call, before the globals are initialized */
- if (pb->cntrlParam.csCode == getGlobalsSC)
- {
- *(long *)pb->cntrlParam.csParam = globe->ramSize;
- if (globe->ramSize == 0)
- {
- Panic("\pDRVRStatus: ramSize is zero");
- }
- result = noErr;
- }
- else if (globe->driveNumber != 0)
- {
- switch(pb->cntrlParam.csCode)
- {
- case driveStatusSC:
- if (pb->cntrlParam.ioVRefNum != globe->driveNumber)
- break;
-
- /* Drive Stats... */
- driveStats = (DrvSts *)pb->cntrlParam.csParam;
- driveStats->track = 0; /* not applicable */
- driveStats->writeProt = 0; /* write enabled */
- driveStats->diskInPlace = 0x08; /* non-ejectable */
- driveStats->installed = 1; /* drive installed */
- driveStats->sides = 0; /* not applicable */
- driveStats->twoSideFmt = 0; /* not applicable */
- driveStats->needsFlush = 0; /* not applicable */
- driveStats->diskErrs = 0; /* not applicable */
-
- /* Copy qLink through dQFSID from our DrvQEl */
- driveQEl = (DrvQElPtr)(GetDrvQHdr()->qHead);
- while(driveQEl != nil)
- {
- if (driveQEl->dQDrive == globe->driveNumber)
- {
- driveStats->qLink = driveQEl->qLink;
- driveStats->qType = driveQEl->qType;
- driveStats->dQDrive = driveQEl->dQDrive;
- driveStats->dQRefNum = driveQEl->dQRefNum;
- driveStats->dQFSID = driveQEl->dQFSID;
-
- break; /* while(driveQEl != nil) */
- }
- driveQEl = (DrvQElPtr)(driveQEl->qLink);
- }
-
- result = noErr;
- break;
-
- default:
- break;
- }
- }
- else
- {
- Panic("\pDRVRStatus: Globals not initialized");
- }
- }
- else
- {
- Panic("\pDRVRStatus: No dCtlStorage");
- result = notOpenErr;
- }
-
- return (result);
- }
-
- /*****************************************************************************/
-
- pascal OSErr DRVRClose (ParmBlkPtr pb, DCtlPtr dce)
- {
- DrvrGlobals *globe;
-
- #pragma unused (pb)
-
- if (dce->dCtlStorage)
- {
- globe = (DrvrGlobals *)dce->dCtlStorage;
-
- if (globe->ramDisk)
- DisposPtr(globe->ramDisk);
-
- DisposPtr((Ptr)dce->dCtlStorage);
- }
-
- return (noErr);
- }
-
- /*****************************************************************************/
- #if (defined(__MWERKS__) || defined(THINK_C))
- /*****************************************************************************/
- /* Metrowerks specific main routine. This isn't used in MPW; we use an */
- /* assembly language header instead. */
- /*****************************************************************************/
-
- OSErr main(ParmBlkPtr paramBlock,DCtlPtr devCtlEnt,short dispatch)
- {
- //
- // Here A4 is already setup to point to our data segment. There is no need
- // to call long oldA4=SetCurrentA4();/SetA4(oldA4); as in code resources.
- //
- // However you have to still have to use "#include <SetupA4.h>;RememberA4();..."
- // when using callback functions.
- //
- // If your routine returns 1 (asynch request can't be completed right away)
- // the Metrowerks startup code will correctly jump to jIODone. You don't need
- // to worry about this issue in this driver.
- //
- OSErr err = noErr;
-
- switch(dispatch)
- {
- case 0: // Open
- err = DRVROpen(paramBlock, devCtlEnt);
- break;
- case 1: // Prime return 1 if async request cannot be completed right away
- err = DRVRPrime(paramBlock, devCtlEnt);
- break;
- case 2: // Control return 1 if async request cannot be completed right away
- err = DRVRControl(paramBlock, devCtlEnt);
- break;
- case 3: // Status return 1 if async request cannot be completed right away
- err = DRVRStatus(paramBlock, devCtlEnt);
- break;
- case 4: // Close
- err = DRVRClose(paramBlock, devCtlEnt);
- break;
- }
- return err;
- }
- #endif // __MWERKS__ or THINK_C
-
-